"""EDA处理器可视化示例

演示如何使用EDA处理器的可视化功能，包括：
- 基础信号可视化
- 峰值检测结果可视化
- 频域分析可视化
- 质量评估可视化
- 交互式可视化
- 批量可视化

适合需要数据可视化和结果展示的用户。
"""

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from typing import Dict, Any, List, Optional
import logging

# 导入EDA处理器模块
from ..core.pipeline import process_eda_pipeline
from ..utils.visualization import (
    plot_eda_signal, plot_peak_detection, plot_frequency_analysis,
    plot_quality_assessment, create_analysis_report
)
from ..utils.batch_processor import process_eda_batch
from ..examples.basic_usage import generate_sample_eda_data

# 设置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False

def basic_visualization_example():
    """基础可视化示例"""
    print("=" * 60)
    print("基础可视化示例")
    print("=" * 60)
    
    # 生成示例数据
    duration = 300  # 5分钟
    sampling_rate = 4.0
    eda_data = generate_sample_eda_data(duration, sampling_rate)
    
    print(f"生成了 {duration} 秒的EDA数据，采样率 {sampling_rate} Hz")
    
    # 处理数据
    result = process_eda_pipeline(eda_data, sampling_rate)
    
    if not result['success']:
        print(f"数据处理失败: {result.get('error', '未知错误')}")
        return
    
    print(f"检测到 {len(result['peaks'])} 个峰值")
    
    # 1. 基础信号可视化
    print("\n1. 绘制基础EDA信号...")
    fig1 = plot_eda_signal(
        eda_data=eda_data,
        sampling_rate=sampling_rate,
        title="EDA信号 - 基础可视化",
        show_grid=True,
        figsize=(12, 6)
    )
    
    if fig1:
        plt.tight_layout()
        plt.show()
        print("   ✓ 基础信号图已显示")
    
    # 2. 峰值检测结果可视化
    print("\n2. 绘制峰值检测结果...")
    fig2 = plot_peak_detection(
        eda_data=eda_data,
        sampling_rate=sampling_rate,
        peaks=result['peaks'],
        processed_signal=result.get('processed_signal'),
        title="EDA峰值检测结果",
        figsize=(14, 8)
    )
    
    if fig2:
        plt.tight_layout()
        plt.show()
        print("   ✓ 峰值检测图已显示")
    
    # 3. 频域分析可视化
    print("\n3. 绘制频域分析...")
    fig3 = plot_frequency_analysis(
        eda_data=eda_data,
        sampling_rate=sampling_rate,
        title="EDA频域分析",
        figsize=(12, 8)
    )
    
    if fig3:
        plt.tight_layout()
        plt.show()
        print("   ✓ 频域分析图已显示")
    
    # 4. 质量评估可视化
    print("\n4. 绘制质量评估...")
    fig4 = plot_quality_assessment(
        quality_result=result['quality'],
        title="EDA信号质量评估",
        figsize=(10, 8)
    )
    
    if fig4:
        plt.tight_layout()
        plt.show()
        print("   ✓ 质量评估图已显示")

def advanced_visualization_example():
    """高级可视化示例"""
    print("\n" + "=" * 60)
    print("高级可视化示例")
    print("=" * 60)
    
    # 生成复杂的测试数据
    duration = 600  # 10分钟
    sampling_rate = 8.0
    eda_data = generate_complex_eda_data(duration, sampling_rate)
    
    print(f"生成了 {duration} 秒的复杂EDA数据，采样率 {sampling_rate} Hz")
    
    # 使用高级配置处理数据
    advanced_config = {
        'preprocessing': {
            'algorithm': 'improved',
            'params': {
                'lowpass_cutoff': 1.0,
                'outlier_threshold': 3.0,
                'detrend_method': 'polynomial'
            }
        },
        'peak_detection': {
            'algorithm': 'improved',
            'params': {
                'min_amplitude': 0.02,
                'min_rise_time': 0.5,
                'max_rise_time': 5.0
            }
        },
        'metrics_calculation': {
            'algorithm': 'advanced',
            'params': {}
        },
        'quality_assessment': {
            'algorithm': 'advanced',
            'params': {}
        }
    }
    
    result = process_eda_pipeline(eda_data, sampling_rate, advanced_config)
    
    if not result['success']:
        print(f"数据处理失败: {result.get('error', '未知错误')}")
        return
    
    print(f"检测到 {len(result['peaks'])} 个峰值")
    print(f"计算了 {len(result['metrics'])} 个指标")
    
    # 创建综合分析图
    print("\n创建综合分析可视化...")
    create_comprehensive_visualization(eda_data, sampling_rate, result)

def interactive_visualization_example():
    """交互式可视化示例"""
    print("\n" + "=" * 60)
    print("交互式可视化示例")
    print("=" * 60)
    
    try:
        import plotly.graph_objects as go
        from plotly.subplots import make_subplots
        import plotly.offline as pyo
        
        # 生成数据
        duration = 180  # 3分钟
        sampling_rate = 4.0
        eda_data = generate_sample_eda_data(duration, sampling_rate)
        
        # 处理数据
        result = process_eda_pipeline(eda_data, sampling_rate)
        
        if not result['success']:
            print(f"数据处理失败: {result.get('error', '未知错误')}")
            return
        
        # 创建交互式图表
        print("创建交互式可视化...")
        create_interactive_visualization(eda_data, sampling_rate, result)
        
    except ImportError:
        print("Plotly未安装，跳过交互式可视化示例")
        print("安装命令: pip install plotly")

def batch_visualization_example():
    """批量可视化示例"""
    print("\n" + "=" * 60)
    print("批量可视化示例")
    print("=" * 60)
    
    # 生成多个数据集
    datasets = {}
    sampling_rate = 4.0
    
    print("生成多个测试数据集...")
    for i, (name, duration) in enumerate([
        ("短时数据", 60),
        ("中时数据", 180),
        ("长时数据", 300)
    ]):
        eda_data = generate_sample_eda_data(duration, sampling_rate)
        datasets[name] = {
            'data': eda_data,
            'sampling_rate': sampling_rate,
            'duration': duration
        }
        print(f"  {i+1}. {name}: {duration}秒")
    
    # 批量处理
    print("\n批量处理数据...")
    results = {}
    for name, dataset in datasets.items():
        result = process_eda_pipeline(dataset['data'], dataset['sampling_rate'])
        if result['success']:
            results[name] = result
            print(f"  ✓ {name}: {len(result['peaks'])} 个峰值")
        else:
            print(f"  ✗ {name}: 处理失败")
    
    # 创建批量比较可视化
    if results:
        print("\n创建批量比较可视化...")
        create_batch_comparison_visualization(datasets, results)

def create_comprehensive_visualization(eda_data: np.ndarray, 
                                     sampling_rate: float, 
                                     result: Dict[str, Any]):
    """创建综合分析可视化"""
    
    # 创建子图
    fig, axes = plt.subplots(2, 2, figsize=(16, 12))
    fig.suptitle('EDA信号综合分析', fontsize=16, fontweight='bold')
    
    # 时间轴
    time = np.arange(len(eda_data)) / sampling_rate
    
    # 1. 原始信号和处理后信号
    ax1 = axes[0, 0]
    ax1.plot(time, eda_data, 'b-', alpha=0.7, linewidth=1, label='原始信号')
    
    if 'processed_signal' in result:
        ax1.plot(time, result['processed_signal'], 'r-', linewidth=1.5, label='处理后信号')
    
    # 标记峰值
    if result['peaks']:
        peak_times = [p['peak_index'] / sampling_rate for p in result['peaks']]
        peak_values = [eda_data[p['peak_index']] for p in result['peaks']]
        ax1.scatter(peak_times, peak_values, color='red', s=50, zorder=5, label=f'峰值 (n={len(result["peaks"])})')
    
    ax1.set_xlabel('时间 (秒)')
    ax1.set_ylabel('EDA (μS)')
    ax1.set_title('信号处理和峰值检测')
    ax1.legend()
    ax1.grid(True, alpha=0.3)
    
    # 2. 峰值特征分析
    ax2 = axes[0, 1]
    if result['peaks']:
        amplitudes = [p.get('amplitude', 0) for p in result['peaks']]
        rise_times = [p.get('rise_time', 0) for p in result['peaks'] if p.get('rise_time', 0) > 0]
        
        if amplitudes:
            ax2.hist(amplitudes, bins=min(10, len(amplitudes)), alpha=0.7, color='skyblue', edgecolor='black')
            ax2.set_xlabel('峰值幅度 (μS)')
            ax2.set_ylabel('频次')
            ax2.set_title('峰值幅度分布')
            ax2.grid(True, alpha=0.3)
        else:
            ax2.text(0.5, 0.5, '无峰值数据', ha='center', va='center', transform=ax2.transAxes)
            ax2.set_title('峰值幅度分布')
    else:
        ax2.text(0.5, 0.5, '未检测到峰值', ha='center', va='center', transform=ax2.transAxes)
        ax2.set_title('峰值幅度分布')
    
    # 3. 频域分析
    ax3 = axes[1, 0]
    from scipy import signal as scipy_signal
    
    freqs, psd = scipy_signal.welch(eda_data, fs=sampling_rate, nperseg=min(len(eda_data)//4, 256))
    ax3.semilogy(freqs, psd, 'b-', linewidth=1.5)
    ax3.set_xlabel('频率 (Hz)')
    ax3.set_ylabel('功率谱密度')
    ax3.set_title('功率谱分析')
    ax3.grid(True, alpha=0.3)
    ax3.set_xlim(0, min(2.0, sampling_rate/2))
    
    # 4. 质量评估雷达图
    ax4 = axes[1, 1]
    
    if 'quality' in result and 'individual_scores' in result['quality']:
        quality_scores = result['quality']['individual_scores']
        
        # 选择主要质量指标
        main_metrics = ['completeness_score', 'noise_score', 'stability_score', 
                       'artifact_score', 'consistency_score']
        
        available_metrics = []
        scores = []
        
        for metric in main_metrics:
            if metric in quality_scores:
                available_metrics.append(metric.replace('_score', '').replace('_', ' ').title())
                scores.append(quality_scores[metric])
        
        if available_metrics and scores:
            # 创建雷达图
            angles = np.linspace(0, 2 * np.pi, len(available_metrics), endpoint=False).tolist()
            scores += scores[:1]  # 闭合图形
            angles += angles[:1]
            
            ax4.plot(angles, scores, 'o-', linewidth=2, color='green', alpha=0.7)
            ax4.fill(angles, scores, alpha=0.25, color='green')
            ax4.set_xticks(angles[:-1])
            ax4.set_xticklabels(available_metrics, fontsize=8)
            ax4.set_ylim(0, 1)
            ax4.set_title('信号质量评估')
            ax4.grid(True)
        else:
            ax4.text(0.5, 0.5, '质量评估数据不可用', ha='center', va='center', transform=ax4.transAxes)
            ax4.set_title('信号质量评估')
    else:
        ax4.text(0.5, 0.5, '质量评估数据不可用', ha='center', va='center', transform=ax4.transAxes)
        ax4.set_title('信号质量评估')
    
    plt.tight_layout()
    plt.show()
    print("   ✓ 综合分析图已显示")

def create_interactive_visualization(eda_data: np.ndarray, 
                                   sampling_rate: float, 
                                   result: Dict[str, Any]):
    """创建交互式可视化"""
    
    import plotly.graph_objects as go
    from plotly.subplots import make_subplots
    import plotly.offline as pyo
    
    # 时间轴
    time = np.arange(len(eda_data)) / sampling_rate
    
    # 创建子图
    fig = make_subplots(
        rows=2, cols=2,
        subplot_titles=('EDA信号和峰值检测', '峰值特征分析', '频域分析', '质量评估'),
        specs=[[{"secondary_y": False}, {"type": "bar"}],
               [{"type": "scatter"}, {"type": "bar"}]]
    )
    
    # 1. EDA信号
    fig.add_trace(
        go.Scatter(x=time, y=eda_data, mode='lines', name='原始信号', 
                  line=dict(color='blue', width=1), opacity=0.7),
        row=1, col=1
    )
    
    if 'processed_signal' in result:
        fig.add_trace(
            go.Scatter(x=time, y=result['processed_signal'], mode='lines', 
                      name='处理后信号', line=dict(color='red', width=2)),
            row=1, col=1
        )
    
    # 标记峰值
    if result['peaks']:
        peak_times = [p['peak_index'] / sampling_rate for p in result['peaks']]
        peak_values = [eda_data[p['peak_index']] for p in result['peaks']]
        
        fig.add_trace(
            go.Scatter(x=peak_times, y=peak_values, mode='markers', 
                      name=f'峰值 (n={len(result["peaks"])})',
                      marker=dict(color='red', size=8, symbol='circle')),
            row=1, col=1
        )
    
    # 2. 峰值幅度分布
    if result['peaks']:
        amplitudes = [p.get('amplitude', 0) for p in result['peaks']]
        if amplitudes:
            fig.add_trace(
                go.Histogram(x=amplitudes, name='幅度分布', nbinsx=10,
                           marker_color='skyblue', opacity=0.7),
                row=1, col=2
            )
    
    # 3. 频域分析
    from scipy import signal as scipy_signal
    freqs, psd = scipy_signal.welch(eda_data, fs=sampling_rate, nperseg=min(len(eda_data)//4, 256))
    
    fig.add_trace(
        go.Scatter(x=freqs, y=psd, mode='lines', name='功率谱密度',
                  line=dict(color='green', width=2)),
        row=2, col=1
    )
    
    # 4. 质量评估
    if 'quality' in result and 'individual_scores' in result['quality']:
        quality_scores = result['quality']['individual_scores']
        
        metrics = list(quality_scores.keys())[:8]  # 显示前8个指标
        scores = [quality_scores[m] for m in metrics]
        
        fig.add_trace(
            go.Bar(x=[m.replace('_score', '').replace('_', ' ').title() for m in metrics], 
                   y=scores, name='质量分数',
                   marker_color='orange', opacity=0.7),
            row=2, col=2
        )
    
    # 更新布局
    fig.update_layout(
        title_text="EDA信号交互式分析",
        title_x=0.5,
        height=800,
        showlegend=True
    )
    
    # 更新坐标轴标签
    fig.update_xaxes(title_text="时间 (秒)", row=1, col=1)
    fig.update_yaxes(title_text="EDA (μS)", row=1, col=1)
    
    fig.update_xaxes(title_text="幅度 (μS)", row=1, col=2)
    fig.update_yaxes(title_text="频次", row=1, col=2)
    
    fig.update_xaxes(title_text="频率 (Hz)", row=2, col=1)
    fig.update_yaxes(title_text="功率谱密度", row=2, col=1, type="log")
    
    fig.update_xaxes(title_text="质量指标", row=2, col=2)
    fig.update_yaxes(title_text="分数", row=2, col=2)
    
    # 保存为HTML文件
    html_file = "eda_interactive_analysis.html"
    pyo.plot(fig, filename=html_file, auto_open=True)
    print(f"   ✓ 交互式图表已保存为 {html_file}")

def create_batch_comparison_visualization(datasets: Dict[str, Dict], 
                                        results: Dict[str, Dict]):
    """创建批量比较可视化"""
    
    # 创建比较图
    fig, axes = plt.subplots(2, 2, figsize=(15, 10))
    fig.suptitle('批量数据比较分析', fontsize=16, fontweight='bold')
    
    # 1. 峰值数量比较
    ax1 = axes[0, 0]
    names = list(results.keys())
    peak_counts = [len(results[name]['peaks']) for name in names]
    
    bars1 = ax1.bar(names, peak_counts, color=['skyblue', 'lightgreen', 'lightcoral'])
    ax1.set_ylabel('峰值数量')
    ax1.set_title('检测到的峰值数量')
    ax1.grid(True, alpha=0.3)
    
    # 添加数值标签
    for bar, count in zip(bars1, peak_counts):
        ax1.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.1,
                str(count), ha='center', va='bottom')
    
    # 2. 质量分数比较
    ax2 = axes[0, 1]
    quality_scores = [results[name]['quality']['overall_score'] for name in names]
    
    bars2 = ax2.bar(names, quality_scores, color=['skyblue', 'lightgreen', 'lightcoral'])
    ax2.set_ylabel('质量分数')
    ax2.set_title('信号质量评估')
    ax2.set_ylim(0, 1)
    ax2.grid(True, alpha=0.3)
    
    # 添加数值标签
    for bar, score in zip(bars2, quality_scores):
        ax2.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.02,
                f'{score:.3f}', ha='center', va='bottom')
    
    # 3. 信号概览
    ax3 = axes[1, 0]
    colors = ['blue', 'green', 'red']
    
    for i, (name, dataset) in enumerate(datasets.items()):
        if name in results:
            time = np.arange(len(dataset['data'])) / dataset['sampling_rate']
            # 只显示前60秒的数据以便比较
            max_samples = int(60 * dataset['sampling_rate'])
            if len(time) > max_samples:
                time = time[:max_samples]
                data = dataset['data'][:max_samples]
            else:
                data = dataset['data']
            
            ax3.plot(time, data + i * 0.5, color=colors[i], alpha=0.7, 
                    linewidth=1, label=f'{name} (偏移 {i*0.5:.1f})')
    
    ax3.set_xlabel('时间 (秒)')
    ax3.set_ylabel('EDA (μS)')
    ax3.set_title('信号概览 (前60秒)')
    ax3.legend()
    ax3.grid(True, alpha=0.3)
    
    # 4. 指标比较
    ax4 = axes[1, 1]
    
    # 选择几个关键指标进行比较
    key_metrics = ['mean_eda', 'std_eda', 'num_peaks', 'peak_rate']
    
    metric_data = {}
    for metric in key_metrics:
        metric_data[metric] = []
        for name in names:
            if metric == 'num_peaks':
                value = len(results[name]['peaks'])
            elif metric == 'peak_rate':
                duration = len(datasets[name]['data']) / datasets[name]['sampling_rate']
                value = len(results[name]['peaks']) / duration * 60  # 每分钟峰值数
            else:
                value = results[name]['metrics'].get(metric, 0)
            metric_data[metric].append(value)
    
    # 归一化数据以便在同一图中显示
    x = np.arange(len(names))
    width = 0.2
    
    for i, metric in enumerate(key_metrics):
        values = metric_data[metric]
        if max(values) > 0:
            normalized_values = [v / max(values) for v in values]
            ax4.bar(x + i * width, normalized_values, width, 
                   label=metric.replace('_', ' ').title(), alpha=0.7)
    
    ax4.set_xlabel('数据集')
    ax4.set_ylabel('归一化值')
    ax4.set_title('关键指标比较 (归一化)')
    ax4.set_xticks(x + width * 1.5)
    ax4.set_xticklabels(names)
    ax4.legend()
    ax4.grid(True, alpha=0.3)
    
    plt.tight_layout()
    plt.show()
    print("   ✓ 批量比较图已显示")

def generate_complex_eda_data(duration: float, sampling_rate: float) -> np.ndarray:
    """生成复杂的EDA测试数据"""
    t = np.arange(0, duration, 1/sampling_rate)
    
    # 基础SCL（更复杂的基线变化）
    scl = (2.0 + 
           0.5 * np.sin(2 * np.pi * t / 120) +  # 2分钟周期
           0.3 * np.sin(2 * np.pi * t / 30) +   # 30秒周期
           0.1 * np.sin(2 * np.pi * t / 10) +   # 10秒周期
           0.05 * t / duration)  # 缓慢上升趋势
    
    # 添加多个SCR事件
    scr = np.zeros_like(t)
    
    # 设置随机种子以获得可重复的结果
    np.random.seed(123)
    
    # 添加不同类型的SCR事件
    event_types = [
        {'rate': 1/60, 'amplitude_range': (0.1, 0.3), 'name': '小幅SCR'},
        {'rate': 1/120, 'amplitude_range': (0.3, 0.6), 'name': '中幅SCR'},
        {'rate': 1/180, 'amplitude_range': (0.6, 1.0), 'name': '大幅SCR'}
    ]
    
    for event_type in event_types:
        num_events = int(duration * event_type['rate'])
        
        for _ in range(num_events):
            event_time = np.random.uniform(10, duration - 20)
            event_idx = int(event_time * sampling_rate)
            
            # SCR参数
            rise_duration = np.random.uniform(1, 4)
            recovery_duration = np.random.uniform(8, 20)
            amplitude = np.random.uniform(*event_type['amplitude_range'])
            
            # 生成SCR波形
            rise_samples = int(rise_duration * sampling_rate)
            recovery_samples = int(recovery_duration * sampling_rate)
            
            if event_idx + rise_samples + recovery_samples < len(t):
                # 上升阶段（指数上升）
                rise_t = np.arange(rise_samples) / sampling_rate
                rise_scr = amplitude * (1 - np.exp(-3 * rise_t / rise_duration))
                
                # 恢复阶段（双指数恢复）
                recovery_t = np.arange(recovery_samples) / sampling_rate
                recovery_scr = amplitude * (0.7 * np.exp(-1.5 * recovery_t / recovery_duration) +
                                          0.3 * np.exp(-0.3 * recovery_t / recovery_duration))
                
                # 添加到信号中
                scr[event_idx:event_idx + rise_samples] += rise_scr
                scr[event_idx + rise_samples:event_idx + rise_samples + recovery_samples] += recovery_scr
    
    # 合成信号
    eda_signal = scl + scr
    
    # 添加不同类型的噪声
    # 1. 高斯白噪声
    white_noise = np.random.normal(0, 0.02, len(t))
    
    # 2. 1/f噪声（粉红噪声）
    pink_noise = generate_pink_noise(len(t)) * 0.01
    
    # 3. 运动伪影（偶发的尖峰）
    motion_artifacts = np.zeros_like(t)
    num_artifacts = int(duration / 60)  # 平均每分钟一个伪影
    
    for _ in range(num_artifacts):
        artifact_time = np.random.uniform(0, duration)
        artifact_idx = int(artifact_time * sampling_rate)
        artifact_width = int(np.random.uniform(0.5, 2.0) * sampling_rate)
        
        if artifact_idx + artifact_width < len(t):
            artifact_amplitude = np.random.uniform(0.1, 0.3)
            artifact_shape = artifact_amplitude * np.exp(-np.arange(artifact_width) / (artifact_width / 3))
            motion_artifacts[artifact_idx:artifact_idx + artifact_width] += artifact_shape
    
    # 合成最终信号
    eda_signal += white_noise + pink_noise + motion_artifacts
    
    return eda_signal

def generate_pink_noise(n_samples: int) -> np.ndarray:
    """生成粉红噪声（1/f噪声）"""
    # 简化的粉红噪声生成
    white_noise = np.random.randn(n_samples)
    
    # 在频域中应用1/f滤波
    fft_white = np.fft.fft(white_noise)
    freqs = np.fft.fftfreq(n_samples)
    
    # 避免除零
    freqs[0] = 1e-10
    
    # 应用1/f滤波
    fft_pink = fft_white / np.sqrt(np.abs(freqs))
    
    # 转换回时域
    pink_noise = np.real(np.fft.ifft(fft_pink))
    
    # 归一化
    pink_noise = pink_noise / np.std(pink_noise)
    
    return pink_noise

if __name__ == "__main__":
    # 运行所有可视化示例
    basic_visualization_example()
    advanced_visualization_example()
    interactive_visualization_example()
    batch_visualization_example()